#include "stdafx.h"
#include "gp.h"
#include "gp_Ax2.h"
#include "gp_Ax1.h"
#include "gp_Pnt.h"
#include "gp_Trsf.h"
#include "gp_Vec.h"
#include "gp_Elips.h"

void gp_Elips::Mirror (const gp_Pnt& P)
{ pos.Mirror(P); }

gp_Elips gp_Elips::Mirrored (const gp_Pnt& P) const
{
	gp_Elips E = *this;
	E.pos.Mirror (P);
	return E; 
}

void gp_Elips::Mirror (const gp_Ax1& A1)
{ pos.Mirror(A1); }

gp_Elips gp_Elips::Mirrored (const gp_Ax1& A1) const
{
	gp_Elips E = *this;
	E.pos.Mirror (A1);
	return E; 
}

void gp_Elips::Mirror (const gp_Ax2& A2)
{ pos.Mirror(A2); }

gp_Elips gp_Elips::Mirrored (const gp_Ax2& A2) const
{
	gp_Elips E = *this;
	E.pos.Mirror (A2);
	return E; 
}
 gp_Elips::gp_Elips () :
majorRadius (DBL_MAX),
minorRadius (DBL_MIN)
{ }

 gp_Elips::gp_Elips (const gp_Ax2& A2,
			   const double MajorRadius,
			   const double MinorRadius) :
			   pos(A2),
			   majorRadius (MajorRadius),
			   minorRadius (MinorRadius)
{ 
	 Standard_ConstructionError_Raise_if
	 (MinorRadius < 0.0 || MajorRadius < MinorRadius, "");
}

 double gp_Elips::Area() const
{ return M_PI * majorRadius * minorRadius; }

 double gp_Elips::MajorRadius() const
{ return majorRadius; }

 double gp_Elips::MinorRadius() const
{ return minorRadius; }

 double gp_Elips::Parameter() const
{ 
  if (majorRadius == 0.0) return 0.0;
  else                    return (minorRadius * minorRadius) / majorRadius;
}

 const gp_Ax2& gp_Elips::Position() const
{ return pos; }

 const gp_Ax1& gp_Elips::Axis ()     const
{ return pos.Axis(); }

 gp_Ax1 gp_Elips::Directrix1() const
{
  double E = Eccentricity();
  Standard_ConstructionError_Raise_if(E <= gp::Resolution(), "");
  gp_XYZ Orig = pos.XDirection().XYZ();
  Orig.Multiply (majorRadius/E);
  Orig.Add (pos.Location().XYZ());
  return gp_Ax1 (gp_Pnt(Orig), pos.YDirection());
}

 gp_Ax1 gp_Elips::Directrix2() const
{
  double E = Eccentricity();
  Standard_ConstructionError_Raise_if(E <= gp::Resolution(), "");
  gp_XYZ Orig = pos.XDirection().XYZ();
  Orig.Multiply (-majorRadius/E);
  Orig.Add (pos.Location().XYZ());
  return gp_Ax1 (gp_Pnt(Orig), pos.YDirection());
}

 double gp_Elips::Eccentricity() const
{
  if (majorRadius == 0.0) { return 0.0; }
  else {
    return sqrt(majorRadius * majorRadius - 
		minorRadius * minorRadius) / majorRadius;
  }
}

 double gp_Elips::Focal() const
{
  return 2.0 * sqrt(majorRadius * majorRadius -
		    minorRadius * minorRadius);
}

 gp_Pnt gp_Elips::Focus1() const
{
  double C = sqrt(majorRadius * majorRadius -
			 minorRadius * minorRadius);
  const gp_Pnt& PP = pos.Location  ();
  const gp_Dir& DD = pos.XDirection();
  return gp_Pnt (PP.X() + C * DD.X(),
		 PP.Y() + C * DD.Y(),
		 PP.Z() + C * DD.Z());
}

 gp_Pnt gp_Elips::Focus2() const
{
  double C = sqrt(majorRadius * majorRadius -
			 minorRadius * minorRadius);
  const gp_Pnt& PP = pos.Location  ();
  const gp_Dir& DD = pos.XDirection();
  return gp_Pnt (PP.X() - C * DD.X(),
		 PP.Y() - C * DD.Y(),
		 PP.Z() - C * DD.Z());
}

 const gp_Pnt& gp_Elips::Location () const
{ return pos.Location(); }

 gp_Ax1 gp_Elips::XAxis () const
{ return gp_Ax1 (pos.Location(), pos.XDirection()); }

 gp_Ax1 gp_Elips::YAxis () const
{ return gp_Ax1 (pos.Location(), pos.YDirection()); }

 void gp_Elips::SetAxis (const gp_Ax1& A1)
{ pos.SetAxis(A1); }

 void gp_Elips::SetPosition (const gp_Ax2& A2)
{ pos = A2; }

 void gp_Elips::SetLocation (const gp_Pnt& P)
{ pos.SetLocation (P); }

 void gp_Elips::SetMajorRadius (const double R)
{ 
  Standard_ConstructionError_Raise_if(R < minorRadius, "");
  majorRadius = R;
}

 void gp_Elips::SetMinorRadius (const double R)
{ 
  Standard_ConstructionError_Raise_if(R < 0 || R>majorRadius, "");
  minorRadius = R;
}

 void gp_Elips::Rotate (const gp_Ax1& A1,
			      const double Ang) { pos.Rotate(A1, Ang); }

 gp_Elips gp_Elips::Rotated (const gp_Ax1& A1,
				   const double Ang) const
{
  gp_Elips E = *this;
  E.pos.Rotate(A1, Ang);
  return E; 
}

 void gp_Elips::Scale (const gp_Pnt& P,
			     const double S)
//  Modified by skv - Fri Apr  8 10:28:10 2005 OCC8559 Begin
// { pos.Scale(P, S); }
{
  majorRadius *= S;
  if (majorRadius < 0) majorRadius = - majorRadius;
  minorRadius *= S;
  if (minorRadius < 0) minorRadius = - minorRadius;
  pos.Scale(P, S);
}
//  Modified by skv - Fri Apr  8 10:28:10 2005 OCC8559 End

 gp_Elips gp_Elips::Scaled (const gp_Pnt& P,
				  const double S) const
{
  gp_Elips E = *this;
  E.majorRadius *= S;
  if (E.majorRadius < 0) E.majorRadius = - E.majorRadius;
  E.minorRadius *= S;
  if (E.minorRadius < 0) E.minorRadius = - E.minorRadius;
  E.pos.Scale(P, S);
  return E; 
}

 void gp_Elips::Transform (const gp_Trsf& T)
{
  majorRadius *= T.ScaleFactor();
  if (majorRadius < 0) majorRadius = - majorRadius;
  minorRadius *= T.ScaleFactor();
  if (minorRadius < 0) minorRadius = - minorRadius;
  pos.Transform(T);
}

 gp_Elips gp_Elips::Transformed (const gp_Trsf& T) const
{
  gp_Elips E = *this;
  E.majorRadius *= T.ScaleFactor();
  if (E.majorRadius < 0) E.majorRadius = - E.majorRadius;
  E.minorRadius *= T.ScaleFactor();
  if (E.minorRadius < 0) E.minorRadius = - E.minorRadius;
  E.pos.Transform(T);
  return E;
}

 void gp_Elips::Translate (const gp_Vec& V) 
{ pos.Translate(V); }

 gp_Elips gp_Elips::Translated (const gp_Vec& V) const 
{
  gp_Elips E = *this;
  E.pos.Translate(V);
  return E; 
}

 void gp_Elips::Translate (const gp_Pnt& P1,
			  const gp_Pnt& P2)
{  pos.Translate(P1, P2); }

 gp_Elips gp_Elips::Translated (const gp_Pnt& P1,
				      const gp_Pnt& P2) const
{
  gp_Elips E = *this;
  E.pos.Translate(P1, P2);
  return E; 
}

